﻿#pragma once

#include <list>
#include <string>
#include <tuple>
#include <windows.h>

#include "../window/window_app.h"
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <ikit.h>

namespace ifire {

constexpr auto CONSOLE_LABEL_COUNT = 3;
class UnitTest;
typedef UnitTest* LPUnitTest;

class TestConsole {
private:
  char printBuffer[1024];
  HWND hLabels[CONSOLE_LABEL_COUNT];
  HWND hEdit;
  int editHeight;
  bool fontSelected;
  int button_align_pos_ = 5; // 当前按钮开始的位置
  int action_align_pos_ = 5; // 当前按钮开始的位置
  int action_top_pos_ = 0;
  std::list<std::tuple<const char*, LPUnitTest>> testList;
  WindowApp* parent_;

protected:
  // 用于测试的项目
  void OnStartTest();

public:
  TestConsole(WindowApp* parent, int editHeight);
  ~TestConsole();

  void Init();
  void BuildActions();
  void Print(const char* format, ...);
  void PrintLine(const char* format, ...);
  void FlushLog();

  HWND AddButton(const char* button_name, int button_id);
  HWND AddActionButton(const char* button_name, int index_id);
  void AddText(const char* str, bool newLine) const;
  void SetText(const char* str);
  void SetDebug(int index, const char* format, ...);
  void OnPaint(HDC hdc);
  void OnCommand(int id);

  void SignTest(const char* str, LPUnitTest unitTest);

private:
  int GetButtonTop() { return parent_->GetHeight() - editHeight - 105; }
  int GetActionTop() { return parent_->GetHeight() - editHeight - 70; }
  HWND GetHandle() { return parent_->GetHandle(); }
  int GetWidth() { return parent_->GetWidth(); }
  int GetHeight() { return parent_->GetHeight(); }
};

/*
 * 测试单元，需要测试的东西继承这个类
 */
class UnitTest {
private:
  float startTime;
  float endTime;
  TestConsole* console;
  char printBuffer[1024];

public:
  UnitTest();
  ~UnitTest() = default;

  virtual void RunTest() = 0;
  void Print(const char* format, ...);
  void PrintLine(const char* format, ...);
  void FlushLog();
  void XM_CALLCONV PrintVector(const char* name, DirectX::FXMVECTOR value);
  void XM_CALLCONV PrintVector4(const char* name, DirectX::FXMVECTOR value);
  void XM_CALLCONV PrintMatrix(const char* name, DirectX::FXMMATRIX value);
  void PrintFloat(const char* name, float value);
  void Assert(const char* description, HRESULT result);
  void Assert(const char* description, bool result);
};

//
std::string wchar_to_char(const std::wstring& wideStr);

} // namespace ifire